package com.docconverter;

import org.apache.pdfbox.io.MemoryUsageSetting;
import org.apache.pdfbox.multipdf.PDFMergerUtility;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.*;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

@Component
public class DocToPdfConverter {
    private static final Logger logger = LoggerFactory.getLogger(DocToPdfConverter.class);
    private static final List<String> SUPPORTED_EXTENSIONS = Arrays.asList(".doc", ".docx");
    private static final String BASE_DIR = "C:\\Users\\gulis\\Desktop";
    private static final String OUTPUT_DIR = "output_pdfs";
    private static final String TEMP_DIR = "temp_docs";
    private static final String ERROR_LOG = "error.log";
    private static final String LIBREOFFICE_PATH = "C:\\Program Files (x86)\\LibreOffice\\program\\soffice.exe";

    public DocToPdfConverter() {
        // 检查LibreOffice是否安装
        if (!checkLibreOfficeInstallation()) {
            throw new RuntimeException("LibreOffice is not installed. Please install LibreOffice first. Expected path: " + LIBREOFFICE_PATH);
        }
    }

    public String convertDocuments(File inputDir) throws Exception {
        if (!inputDir.exists() || !inputDir.isDirectory()) {
            throw new IllegalArgumentException("Input path must be a valid directory");
        }

        // 创建输出目录和临时目录
        Path outputDirPath = Paths.get(BASE_DIR, OUTPUT_DIR).toAbsolutePath().normalize();
        Path tempDirPath = Paths.get(BASE_DIR, TEMP_DIR).toAbsolutePath().normalize();
        
        try {
            // 如果输出目录存在，先删除它
            if (Files.exists(outputDirPath)) {
                deleteDirectory(outputDirPath.toFile());
            }
            if (Files.exists(tempDirPath)) {
                deleteDirectory(tempDirPath.toFile());
            }
            
            // 创建新的目录
            Files.createDirectories(outputDirPath);
            Files.createDirectories(tempDirPath);
        } catch (IOException e) {
            throw new IOException("Failed to create directories: " + e.getMessage());
        }

        // 获取所有Word文档
        List<File> documents = getWordDocuments(inputDir);
        if (documents.isEmpty()) {
            throw new IllegalArgumentException("No Word documents found in the input directory.");
        }

        // 按文件名排序
        documents.sort(Comparator.comparing(File::getName));

        // 转换文档
        Map<File, Path> convertedFiles = processDocuments(documents, outputDirPath.toFile(), tempDirPath.toFile());

        if (!convertedFiles.isEmpty()) {
            // 如果只有一个文件，直接返回转换后的文件名
            if (documents.size() == 1) {
                Path pdfPath = convertedFiles.get(documents.get(0));
                return pdfPath.getFileName().toString();
            }

            // 如果有多个文件，创建合并的PDF
            String timestamp = String.valueOf(System.currentTimeMillis());
            String outputFileName = "merged_" + timestamp + ".pdf";
            Path outputFilePath = outputDirPath.resolve(outputFileName);

            try {
                mergePDFs(documents, convertedFiles, outputFilePath);
                logger.info("PDF files have been merged successfully into: {}", outputFilePath);
                
                // 删除临时PDF文件
                for (Path pdf : convertedFiles.values()) {
                    if (!pdf.equals(outputFilePath)) {
                        Files.deleteIfExists(pdf);
                    }
                }

                return outputFileName;
            } catch (IOException e) {
                logger.error("Failed to merge PDF files", e);
                throw new IOException("Failed to merge PDF files: " + e.getMessage());
            }
        }

        // 清理临时目录
        try {
            deleteDirectory(tempDirPath.toFile());
        } catch (IOException e) {
            logger.error("Failed to delete temp directory", e);
        }

        return null;
    }

    private void mergePDFs(List<File> originalDocuments, Map<File, Path> convertedFiles, Path outputPath) throws IOException {
        PDFMergerUtility merger = new PDFMergerUtility();
        merger.setDestinationFileName(outputPath.toString());
        
        // 按原始文档顺序添加PDF文件
        List<File> pdfFiles = new ArrayList<>();
        for (File doc : originalDocuments) {
            Path pdfPath = convertedFiles.get(doc);
            if (pdfPath != null && Files.exists(pdfPath)) {
                pdfFiles.add(pdfPath.toFile());
                logger.info("添加文件到合并列表: {}", pdfPath.getFileName());
            } else {
                logger.warn("跳过缺失的PDF文件: {}", doc.getName());
            }
        }
        
        if (pdfFiles.isEmpty()) {
            throw new IOException("没有可用的PDF文件进行合并");
        }

        // 如果只有一个文件，直接复制而不是合并
        if (pdfFiles.size() == 1) {
            Files.copy(pdfFiles.get(0).toPath(), outputPath, StandardCopyOption.REPLACE_EXISTING);
            logger.info("仅有一个PDF文件，直接复制: {} -> {}", pdfFiles.get(0).getName(), outputPath);
            return;
        }

        // 添加所有源文件
        for (File pdf : pdfFiles) {
            merger.addSource(pdf);
        }
        
        // 使用内存优化设置
        merger.mergeDocuments(MemoryUsageSetting.setupMainMemoryOnly());
        logger.info("PDF文件合并完成: {}", outputPath);
    }

    private void deleteDirectory(File dir) throws IOException {
        if (Files.exists(dir.toPath())) {
            Files.walk(dir.toPath())
                .sorted(java.util.Comparator.reverseOrder())
                .map(Path::toFile)
                .forEach(file -> {
                    try {
                        Files.deleteIfExists(file.toPath());
                    } catch (IOException e) {
                        logger.error("Failed to delete file: {}", file, e);
                    }
                });
        }
    }

    private boolean checkLibreOfficeInstallation() {
        File libreOffice = new File(LIBREOFFICE_PATH);
        return libreOffice.exists() && libreOffice.canExecute();
    }

    private List<File> getWordDocuments(File directory) {
        File[] files = directory.listFiles();
        if (files == null) return List.of();

        logger.info("扫描目录中的所有文件：");
        for (File file : files) {
            logger.info("发现文件: {} (是否为文件: {}, 大小: {} bytes)", 
                file.getName(), 
                file.isFile(),
                file.length());
        }

        List<File> wordDocs = Arrays.stream(files)
                .filter(file -> SUPPORTED_EXTENSIONS.stream()
                        .anyMatch(ext -> file.getName().toLowerCase().endsWith(ext)))
                .collect(Collectors.toList());

        logger.info("找到 {} 个Word文档：", wordDocs.size());
        for (File doc : wordDocs) {
            logger.info("Word文档: {}", doc.getName());
        }

        return wordDocs;
    }

    private Map<File, Path> processDocuments(List<File> documents, File outputDir, File tempDir) {
        AtomicInteger processedCount = new AtomicInteger(0);
        int totalFiles = documents.size();
        Map<File, Path> convertedFiles = new HashMap<>();

        logger.info("开始处理 {} 个文档", totalFiles);
        for (File doc : documents) {
            logger.info("准备处理文档: {}", doc.getName());
        }

        // 使用串行处理替代并行处理，以避免LibreOffice的并发问题
        for (File doc : documents) {
            try {
                logger.info("开始处理文件: {}", doc.getName());
                
                // 创建临时文件（使用UUID避免中文文件名）
                String tempFileName = UUID.randomUUID().toString() + doc.getName().substring(doc.getName().lastIndexOf('.'));
                File tempFile = new File(tempDir, tempFileName);
                Files.copy(doc.toPath(), tempFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
                logger.info("已创建临时文件: {}", tempFile.getAbsolutePath());

                // 构建LibreOffice命令
                ProcessBuilder pb = new ProcessBuilder(
                    LIBREOFFICE_PATH,
                    "--headless",
                    "--convert-to", "pdf:writer_pdf_Export",
                    "--outdir", outputDir.getAbsolutePath(),
                    tempFile.getAbsolutePath()
                );

                // 设置进程优先级
                pb.inheritIO();
                
                logger.info("正在转换第 {}/{} 个文件: {}", 
                    processedCount.incrementAndGet(), totalFiles, doc.getName());
                
                Process process = pb.start();
                logger.info("LibreOffice进程已启动，等待转换完成: {}", doc.getName());
                
                // 等待进程完成，增加超时时间到30秒
                if (!process.waitFor(30, TimeUnit.SECONDS)) {
                    process.destroyForcibly();
                    throw new RuntimeException("转换超时");
                }
                
                int exitCode = process.exitValue();
                logger.info("文件转换完成: {}，退出代码: {}", doc.getName(), exitCode);
                
                if (exitCode != 0) {
                    throw new RuntimeException("转换失败，退出代码: " + exitCode);
                }

                // 使用原始文件名（将扩展名改为.pdf）
                String originalName = doc.getName();
                String pdfName = originalName.substring(0, originalName.lastIndexOf('.')) + ".pdf";
                logger.info("生成PDF文件名: {}", pdfName);
                
                // 重命名生成的PDF文件
                Path sourcePath = outputDir.toPath().resolve(tempFileName.replace(doc.getName().substring(doc.getName().lastIndexOf('.')), ".pdf"));
                Path targetPath = outputDir.toPath().resolve(pdfName);
                
                if (Files.exists(sourcePath)) {
                    // 移动文件
                    Files.move(sourcePath, targetPath, StandardCopyOption.REPLACE_EXISTING);
                    convertedFiles.put(doc, targetPath);
                    logger.info("成功转换并重命名文件: {} -> {}", doc.getName(), pdfName);
                    
                    // 验证生成的PDF文件
                    if (Files.size(targetPath) == 0) {
                        throw new IOException("生成的PDF文件是空的");
                    }
                } else {
                    throw new IOException("未找到生成的PDF文件: " + sourcePath);
                }

                // 删除临时文件
                Files.deleteIfExists(tempFile.toPath());
                logger.info("已删除临时文件: {}", tempFile.getAbsolutePath());
                
                // 等待一小段时间，确保文件系统操作完成
                Thread.sleep(1000);
                
            } catch (Exception e) {
                String errorMessage = String.format("转换文件 %s 失败: %s%n", 
                    doc.getName(), e.getMessage());
                logger.error(errorMessage, e);
                
                try {
                    Files.write(
                        Paths.get(ERROR_LOG), 
                        errorMessage.getBytes(Charset.defaultCharset()), 
                        StandardOpenOption.CREATE, 
                        StandardOpenOption.APPEND
                    );
                } catch (IOException ioe) {
                    logger.error("写入错误日志失败", ioe);
                }
            }
        }

        logger.info("转换完成！");
        logger.info("成功处理: {}/{} 个文件", processedCount.get(), totalFiles);
        logger.info("输出目录: {}", outputDir.getAbsolutePath());
        
        // 打印所有成功转换的文件
        logger.info("成功转换的文件列表：");
        convertedFiles.forEach((doc, path) -> {
            logger.info("- {} -> {}", doc.getName(), path.getFileName());
        });
        
        return convertedFiles;
    }
} 